﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace KC.Library.Net
{
	public partial class Web
	{
		/// <summary>Options used for Web methods that use Hyperlinks</summary>
		public enum HyperlinkOption { All, Broken, Working }

		/// <summary>Gets a list of broken IMG tags in an HTML string.</summary>
		/// <param name="Html">HTML code to parse</param>
		/// <returns>List of IMG tags in the HTML which match the given HyperLinkOption</returns>
		public static List<string> BuildListOfImgTags(string Html, HyperlinkOption hlo)
		{ return GetLinks(GetImagesFromHtml(Html), hlo); }
		/// <summary>Extracts all hyperlinks from an HTML body.</summary>
		/// <param name="HtmlBody">HTML body</param>
		/// <returns>List of all hyperlinks contained therein</returns>
		public static List<string> GetLinksFromHtml(string Body)
		{
			List<string> links = new List<string>();
			foreach (Match m in Regex.Matches(Body, @"(<a.*?>.*?</a>)", RegexOptions.Singleline)) {
				Match m2 = Regex.Match(m.Groups[1].Value, @"href=\""(.*?)\""", RegexOptions.Singleline);
				if (m2.Success && !m2.Groups[1].Value.ToLower().Contains("mailto:") && m2.Groups[1].Value.Contains("://"))
					links.Add(m2.Groups[1].Value); }

			return links;
		}
		/// <summary>Extracts all hyperlinks from an HTML body.</summary>
		/// <param name="HtmlBody">HTML body</param>
		/// <returns>List of all hyperlinks contained therein</returns>
		public static List<string> GetLinksFromHtml(string Body, string url)
		{
			Body = Body.ToLower();
			List<string> links = new List<string>();
			if (Body.Contains("<body")) Body=Body.Substring(Body.IndexOf("<body"));
			if (Body.Contains("</body")) Body=Body.Substring(0,Body.IndexOf("</body"));
			Body = Body.Replace("\'", "\"");

			for (int i = 0; i < Body.Length; i++) {
				if (!Body.Substring(i).StartsWith("href=")) continue;
				string link = Body.Substring(i+5);
				if (link.Contains(">")) link = link.Substring(0, link.IndexOf(">"));
				if (link.Length > 200) continue;
				link = link.TrimStart(new char[] { '\'', '\"' });
				if (link.Contains("\"")) link = link.Substring(0, link.IndexOf("\""));
				if (link.Contains("\'")) link = link.Substring(0, link.IndexOf("\'"));
				if (link.EndsWith(".jpg") || link.EndsWith(".gif") || link.EndsWith(".png") || link.EndsWith(".bmp") || link.EndsWith(".tif") || link.EndsWith(".tiff")) continue;
				if (link.Contains("//") && !link.Contains("://")) continue;
				if (!link.Contains("://")) try { link = new Uri(new Uri(url), link).AbsoluteUri; } catch { continue; }
				link = link.Replace("https://", "http://");
				if (!link.Contains("http://")) continue;
				link = link.Substring(link.IndexOf("http://"));
				links.Add(link);
			}
			return links;
		}
		/// <summary>Gets a list of Images in an HTMl string.</summary>
		/// <param name="Body">HTML code to parse</param>
		/// <returns>List of Images in the HTML</returns>
		public static List<string> GetImagesFromHtml(string Body)
		{
			if (string.IsNullOrEmpty(Body)) throw new ArgumentNullException("Body");

			List<string> links = new List<string>();
			foreach (Match m in Regex.Matches(Body, @"(src\=|http\://.*)(A-Za-z0-9-_\.)*?(\.)(jpg|jpeg|gif|bmp|png|tif|tiff?)"))
				links.Add(m.Value);
			for (int i = 0; i < links.Count; i++) {
				links[i] = links[i].Replace("\"", "").Replace("\'", "").Trim();
				if (links[i].ToLower().Contains("src=")) links[i] = links[i].Substring(links[i].ToLower().IndexOf("src=") + 4);
				links[i] = links[i].TrimStart(new char[] { '/', '\\', '\"', '\'' }).TrimEnd(new char[] { '/', '\\', '\"', '\'' });
				if (links[i].Contains("\"")) links[i] = links[i].Substring(0, links[i].IndexOf("\""));
				if (links[i].Contains("\'")) links[i] = links[i].Substring(0, links[i].IndexOf("\'")); 
			}
			return links;
		}
		/// <summary>Gets a list of Images in an HTMl string.</summary>
		/// <param name="Body">HTML code to parse</param>
		/// <param name="url">URL to prepend relative URL paths with</param>
		/// <returns>List of Images in the HTML</returns>
		public static List<string> GetImagesFromHtml(string Body, string url)
		{
			Body = Body.ToLower().Replace("https", "http").Replace("\'", "\"").Replace("\\", "/");
			List<string> links = new List<string>();
			if (Body.Contains("<body")) Body = Body.Substring(Body.IndexOf("<body"));
			if (Body.Contains("</body")) Body = Body.Substring(0, Body.IndexOf("</body"));

			for (int i = 1; i < Body.Length; i++) {
				string link = Body.Substring(i);
				if (!new char[] { '\'', '\"' }.Contains(Body[i - 1])) continue;
				if (!link.Contains("'") && !link.Contains("\"")) continue;
				foreach (string str in new string[] { ">", "\'", "\"" }) if (link.Contains(str)) link = link.Substring(0, link.IndexOf(str));
				bool overrideBreak = false;
				string[] extensions = new string[] { ".jpg", ".gif", ".png", ".bmp", ".tiff", ".tif" };
				if (extensions.Where(e => link.Contains(e)).Count() == 0) continue;
				foreach (string str in extensions)
					if (link.Contains(str)) link = link.Substring(0, link.IndexOf(str) + str.Length);
				if (overrideBreak || link.Length > 500 || link.Contains("=") || link.Contains("script")) continue;

				if (!link.Contains("://")) link = new Uri(new Uri(url), link).AbsoluteUri;
				link = link.Replace("https://", "http://");
				if (!link.Contains("http://")) continue;
				link = link.Substring(link.IndexOf("http://"));
				links.Add(link); }
			return links;
		}
		/// <summary>Filters a list of links by their operational status</summary>
		/// <param name="links">Links to parse</param>
		/// <param name="hlo">Option dictating which links to return</param>
		/// <returns>List of links that match the options passed in</returns>
		public static List<string> GetLinks(List<string> links, HyperlinkOption hlo)
		{
			if (links == null)
				throw new ArgumentNullException("links", "Links cannot be null");
			if (links.Count == 0)
				return new List<string>();
			if (hlo == HyperlinkOption.All) return links;

			List<string> BrokenLinks = new List<string>();
			foreach (string link in links)
				using (System.Net.WebClient wc = new System.Net.WebClient())
					try
					{
						wc.DownloadData(link);
						if (hlo == HyperlinkOption.Working) BrokenLinks.Add(link);
					}
					catch { if (hlo == HyperlinkOption.Broken) BrokenLinks.Add(link); }
			return BrokenLinks;
		}
		public static bool isUrlBanned(string url)
		{
			url = url.ToLower();
			return url.Contains(".mil")
				|| url.Contains(".gov")
				|| url.Contains("google")
				|| url.Contains("microsoft")
				|| url.Contains("msdn")
				|| url.Contains("bing")
				|| url.Contains("co.us")
				|| url.Contains("comcast");
		}
	}
}
